home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _BE12FAC8E5094055B720C8DDCB8D36D7 < prev    next >
Encoding:
Text File  |  2002-04-26  |  8.1 KB  |  353 lines

  1. // Copyright (C) 2001-2002 Raven Software
  2. //
  3. // bg_slidemove.c -- part of bg_pmove functionality
  4.  
  5. #include "q_shared.h"
  6. #include "bg_public.h"
  7. #include "bg_local.h"
  8.  
  9. /*
  10. ==================
  11. PM_SlideMove
  12.  
  13. Returns qtrue if the velocity was clipped in some way
  14. ==================
  15. */
  16. #define    MAX_CLIP_PLANES    5
  17.  
  18. qboolean    PM_SlideMove( qboolean gravity ) 
  19. {
  20.     int            bumpcount, numbumps;
  21.     vec3_t        dir;
  22.     float        d;
  23.     int            numplanes;
  24.     vec3_t        planes[MAX_CLIP_PLANES];
  25.     vec3_t        primal_velocity;
  26.     vec3_t        clipVelocity;
  27.     int            i, j, k;
  28.     trace_t        trace;
  29.     vec3_t        end;
  30.     float        time_left;
  31.     float        into;
  32.     vec3_t        endVelocity;
  33.     vec3_t        endClipVelocity;
  34.     
  35.     numbumps = 4;
  36.  
  37.     VectorCopy (pm->ps->velocity, primal_velocity);
  38.  
  39.     if ( gravity ) 
  40.     {
  41.         VectorCopy( pm->ps->velocity, endVelocity );
  42.         endVelocity[2] -= pm->ps->gravity * pml.frametime;
  43.         pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
  44.         primal_velocity[2] = endVelocity[2];
  45.         
  46.         if ( pml.groundPlane ) 
  47.         {
  48.             // slide along the ground plane
  49.             PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
  50.                 pm->ps->velocity, OVERCLIP );
  51.         }
  52.     }
  53.  
  54.     time_left = pml.frametime;
  55.  
  56.     // never turn against the ground plane
  57.     if ( pml.groundPlane ) 
  58.     {
  59.         numplanes = 1;
  60.         VectorCopy( pml.groundTrace.plane.normal, planes[0] );
  61.     } 
  62.     else 
  63.     {
  64.         numplanes = 0;
  65.     }
  66.  
  67.     // never turn against original velocity
  68.     VectorNormalize2( pm->ps->velocity, planes[numplanes] );
  69.     numplanes++;
  70.  
  71.     for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ ) 
  72.     {
  73.         // calculate position we are trying to move to
  74.         VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
  75.  
  76.         // see if we can make it there
  77.         pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
  78.  
  79.         if (trace.allsolid) 
  80.         {
  81.             // entity is completely trapped in another solid
  82.             pm->ps->velocity[2] = 0;    // don't build up falling damage, but allow sideways acceleration
  83.             return qtrue;
  84.         }
  85.  
  86.         if (trace.fraction > 0) 
  87.         {
  88.             // actually covered some distance
  89.             VectorCopy (trace.endpos, pm->ps->origin);
  90.         }
  91.  
  92.         if (trace.fraction == 1) 
  93.         {
  94.              break;        // moved the entire distance
  95.         }
  96.  
  97.         // save entity for contact
  98.         PM_AddTouchEnt( trace.entityNum );
  99.  
  100.         time_left -= time_left * trace.fraction;
  101.  
  102.         if (numplanes >= MAX_CLIP_PLANES) 
  103.         {
  104.             // this shouldn't really happen
  105.             VectorClear( pm->ps->velocity );
  106.             return qtrue;
  107.         }
  108.  
  109.         //
  110.         // if this is the same plane we hit before, nudge velocity
  111.         // out along it, which fixes some epsilon issues with
  112.         // non-axial planes
  113.         //
  114.         for ( i = 0 ; i < numplanes ; i++ ) 
  115.         {
  116.             if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) 
  117.             {
  118.                 VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
  119.                 break;
  120.             }
  121.         }
  122.  
  123.         if ( i < numplanes ) 
  124.         {
  125.             continue;
  126.         }
  127.  
  128.         VectorCopy (trace.plane.normal, planes[numplanes]);
  129.         numplanes++;
  130.  
  131.         //
  132.         // modify velocity so it parallels all of the clip planes
  133.         //
  134.  
  135.         // find a plane that it enters
  136.         for ( i = 0 ; i < numplanes ; i++ ) 
  137.         {
  138.             into = DotProduct( pm->ps->velocity, planes[i] );
  139.             if ( into >= 0.1 ) 
  140.             {
  141.                 continue;        // move doesn't interact with the plane
  142.             }
  143.  
  144.             // see how hard we are hitting things
  145.             if ( -into > pml.impactSpeed ) 
  146.             {
  147.                 pml.impactSpeed = -into;
  148.             }
  149.  
  150.             // slide along the plane
  151.             PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
  152.  
  153.             // slide along the plane
  154.             PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );
  155.  
  156.             // see if there is a second plane that the new move enters
  157.             for ( j = 0 ; j < numplanes ; j++ ) 
  158.             {
  159.                 if ( j == i ) 
  160.                 {
  161.                     continue;
  162.                 }
  163.                 if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) 
  164.                 {
  165.                     continue;        // move doesn't interact with the plane
  166.                 }
  167.  
  168.                 // try clipping the move to the plane
  169.                 PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
  170.                 PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
  171.  
  172.                 // see if it goes back into the first clip plane
  173.                 if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) 
  174.                 {
  175.                     continue;
  176.                 }
  177.  
  178.                 // slide the original velocity along the crease
  179.                 CrossProduct (planes[i], planes[j], dir);
  180.                 VectorNormalize( dir );
  181.                 d = DotProduct( dir, pm->ps->velocity );
  182.                 VectorScale( dir, d, clipVelocity );
  183.  
  184.                 CrossProduct (planes[i], planes[j], dir);
  185.                 VectorNormalize( dir );
  186.                 d = DotProduct( dir, endVelocity );
  187.                 VectorScale( dir, d, endClipVelocity );
  188.  
  189.                 // see if there is a third plane the the new move enters
  190.                 for ( k = 0 ; k < numplanes ; k++ ) 
  191.                 {
  192.                     if ( k == i || k == j ) 
  193.                     {
  194.                         continue;
  195.                     }
  196.                     if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) 
  197.                     {
  198.                         continue;        // move doesn't interact with the plane
  199.                     }
  200.  
  201.                     // stop dead at a tripple plane interaction
  202.                     VectorClear( pm->ps->velocity );
  203.                     return qtrue;
  204.                 }
  205.             }
  206.  
  207.             // if we have fixed all interactions, try another move
  208.             VectorCopy( clipVelocity, pm->ps->velocity );
  209.             VectorCopy( endClipVelocity, endVelocity );
  210.             break;
  211.         }
  212.     }
  213.  
  214.     if ( gravity ) 
  215.     {
  216.         VectorCopy( endVelocity, pm->ps->velocity );
  217.     }
  218.  
  219.     // don't change velocity if in a timer (FIXME: is this correct?)
  220.     if ( pm->ps->pm_time ) 
  221.     {
  222.         VectorCopy( primal_velocity, pm->ps->velocity );
  223.     }
  224.  
  225.     return (qboolean)( bumpcount != 0 );
  226. }
  227.  
  228. /*
  229. ==================
  230. PM_StepSlideMove
  231.  
  232. ==================
  233. */
  234. void PM_StepSlideMove( qboolean gravity ) 
  235. {
  236.     trace_t        trace;
  237.     vec3_t        down;
  238.     vec3_t        up = {0, 0, 1};
  239.     qboolean    result = qtrue;
  240.     vec3_t        start_o;
  241.     vec3_t        start_v;
  242.     vec3_t        save_o;
  243.     vec3_t        save_v;
  244.     int            stepsize;
  245.     float        delta;
  246.  
  247.     VectorCopy (pm->ps->origin, start_o);
  248.     VectorCopy (pm->ps->velocity, start_v);
  249.  
  250.     if ( PM_SlideMove( gravity ) == 0 ) 
  251.     {
  252.         // we got exactly where we wanted to go on the first try    
  253.         return;        
  254.     }
  255.  
  256.     // Set the standard stepsize
  257.     stepsize = STEPSIZE;
  258.  
  259.     // Add to the step size if we are crouched when jumping
  260.     if ( pm->ps->pm_flags & PMF_CROUCH_JUMP )
  261.     {
  262.         stepsize += (DEFAULT_VIEWHEIGHT-CROUCH_VIEWHEIGHT);
  263.     }
  264.  
  265.     // Save the origin and velocity in case we have to undo
  266.     VectorCopy ( pm->ps->origin, save_o );
  267.     VectorCopy ( pm->ps->velocity, save_v );
  268.  
  269.     // First lets see if there is any hope of steping up
  270.     pm->maxs[2] -= stepsize;
  271.  
  272.     VectorCopy ( start_o, pm->ps->origin );
  273.     VectorCopy ( start_v, pm->ps->velocity );
  274.  
  275.     pm->ps->origin[2] += stepsize;
  276.  
  277.     // try the move with the altered hit box
  278.     if ( PM_SlideMove( gravity ))
  279.     {
  280.     }
  281.  
  282.     // See how far down now
  283.     VectorCopy ( pm->ps->origin, down );
  284.     down[2] -= stepsize;
  285.  
  286.     // Trace it
  287.     pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
  288.  
  289.     // Return the players hitbox to normal
  290.     pm->maxs[2] += stepsize;
  291.  
  292.     // No stepping up if you have upward velocity
  293.     if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7)) 
  294.     {
  295.         VectorCopy ( save_o, pm->ps->origin );
  296.         VectorCopy ( save_v, pm->ps->velocity );
  297.         return;
  298.     }
  299.  
  300.     if ( trace.allsolid || trace.startsolid ) 
  301.     {
  302.         result = qfalse;
  303.     }
  304.     else
  305.     {
  306.         if ( trace.fraction < 1.0 )
  307.             PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
  308.  
  309.         // Now double check not stuck
  310.         VectorCopy ( trace.endpos, pm->ps->origin );
  311.         pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask);
  312.  
  313.         if ( trace.allsolid || trace.startsolid )
  314.             result = qfalse;
  315.     }
  316.     
  317.     if ( !result )
  318.     {
  319.         VectorCopy ( save_o, pm->ps->origin );
  320.         VectorCopy ( save_v, pm->ps->velocity );
  321.     }
  322.  
  323.     // use the step move
  324.     delta = pm->ps->origin[2] - start_o[2];
  325.  
  326.     // Shoould we send a step event?
  327.     if ( delta > 2 ) 
  328.     {
  329.         if ( delta < 7 ) 
  330.         {
  331.             PM_AddEvent( EV_STEP_4 );
  332.         } 
  333.         else if ( delta < 11 ) 
  334.         {
  335.             PM_AddEvent( EV_STEP_8 );
  336.         } 
  337.         else if ( delta < 15 ) 
  338.         {
  339.             PM_AddEvent( EV_STEP_12 );
  340.         } 
  341.         else 
  342.         {
  343.             PM_AddEvent( EV_STEP_16 );
  344.         }
  345.     }
  346.     
  347.     if ( pm->debugLevel ) 
  348.     {
  349.         Com_Printf("%i:stepped\n", c_pmove);
  350.     }
  351. }
  352.  
  353.